package com.common.utils;

import com.aliyun.oss.common.utils.IOUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import com.alibaba.fastjson.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static org.apache.http.client.config.RequestConfig.*;

@Slf4j
public class SpiderUtil {
    private static final CloseableHttpClient client;
    static {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        //设置整个连接池最大连接数 根据自己的场景决定
        connectionManager.setMaxTotal(500);

        //路由是对maxTotal的细分,针对一个url的最大并发数,每路由最大连接数，默认值是2
        connectionManager.setDefaultMaxPerRoute(10);
        //针对所有的请求设置超时时间,也可以放到后面针对某一个url设置这些个超时时间
        RequestConfig requestConfig = custom()
                .setSocketTimeout(10000) //服务器返回数据(response)的时间，超过该时间抛出read timeout
                .setConnectTimeout(5000)//连接上服务器(握手成功)的时间，超出该时间抛出connect timeout
                .setConnectionRequestTimeout(1000)//从连接池中获取连接的超时时间，超过该时间未拿到可用连接，会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                .build();

        client = HttpClientBuilder.create()
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                //设置后台线程剔除失效连接
                .evictExpiredConnections().evictIdleConnections(5000, TimeUnit.SECONDS)
                .build();
    }
    /*
    * 搜索标题，获取文章列表
    * String  keyWord 搜索内容
    * */
    public static List<Essay> getEssays(String keyWord){
        List<Essay> essays = new ArrayList<>();
        try {
            URI uri = new URIBuilder("https://so.csdn.net/api/v3/search")
                    .setParameter("q", keyWord)
                    .setParameter("platform", "pc")
                    .build();
            HttpGet httpGet = new HttpGet(uri);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");
            httpGet.setHeader("Accept", "application/json, text/javascript, */*; q=0.01");
            httpGet.setHeader("Content-Type", "application/json;charset=UTF-8");
            httpGet.setHeader("Origin", "https://blog.csdn.net");
            httpGet.setHeader("Accept-Encoding", "gzip, deflate, br");

            CloseableHttpResponse response = client.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                InputStream content = entity.getContent();
                String str = IOUtils.readStreamAsString(content, "UTF-8");
                JSONObject jsonObject = JSONObject.parseObject(str);
                JSONArray resultVos = jsonObject.getJSONArray("result_vos");
                for (int i = 0;i < resultVos.size();i++){
                    JSONObject essayObject = (JSONObject) resultVos.get(i);
                    String title = essayObject.getString("title");
                    title = removeLabel(title);
                    String url = essayObject.getString("url");
                    Essay essay = new Essay(title,url);
                    essays.add(essay);
                }
                return essays;
            }else return null;
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /*
    * 获取与搜索词相关的热词
    * String word 搜索词
    * */
    public static List<String> getAssociateWord(String word){
        List<String> associateWords = new ArrayList<>();
        try {
            URI uri = new URIBuilder("https://silkroad.csdn.net/api/v2/rcmd/list/channel/pc_toolbar_associateword")
                    .build();
            HttpPost httpPost = new HttpPost(uri);
            httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");
            httpPost.setHeader("Accept", "application/json, text/javascript, */*; q=0.01");
            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setHeader("Origin", "https://blog.csdn.net");
            httpPost.setHeader("Accept-Encoding", "gzip, deflate, br");


            JSONObject ext = new JSONObject();
            ext.put("query",word);
            ext.put("platform","pc");
            ext.put("pageSize","10");
            ext.put("type","suggest");

            JSONObject params = new JSONObject();
            params.put("channel","pc_toolbar_associateword");
            params.put("ext",ext);
            params.put("size","10");

            StringEntity stringEntity = new StringEntity(String.valueOf(params),"UTF-8");
            httpPost.setEntity(stringEntity);
            CloseableHttpResponse response = client.execute(httpPost);
            System.out.println(response.getStatusLine().getStatusCode());

            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                InputStream content = entity.getContent();
                String str = IOUtils.readStreamAsString(content, "UTF-8");
                JSONObject jsonObject = JSONObject.parseObject(str);
                JSONObject data = (JSONObject) jsonObject.get("data");
                JSONArray items = data.getJSONArray("items");
                for (int i = 0;i < items.size();i++){
                    JSONObject item = (JSONObject) items.get(i);
                    String associatedWord = (String)item.get("product_id");
                    associatedWord = removeLabel(associatedWord);
                    associateWords.add(associatedWord);
                }
                return associateWords;
            }else return null;
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    /*
    * 根据传入的文章地址，
    * 以html字符串返回文章内容
    * */
    public static String getEssayContent(String url){
        try {
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");
            httpGet.setHeader("Accept", "application/json, text/javascript, */*; q=0.01");
            httpGet.setHeader("Content-Type", "application/json;charset=UTF-8");
            httpGet.setHeader("Origin", "https://blog.csdn.net");
            httpGet.setHeader("Accept-Encoding", "gzip, deflate, br");

            CloseableHttpResponse response = client.execute(httpGet);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                String str = EntityUtils.toString(entity);
                Document html = Jsoup.parse(str);
                Elements content = html.getElementsByClass("blog-content-box");
                String res = content.toString();
                return res;
            }else return null;
        } catch (ClientProtocolException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static String removeLabel(String str){
        String htmlRegex = "<[^>]+>";
        return str.replaceAll(htmlRegex, "");
    }
}
